﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MongoDB;
using MongoDB.Configuration;
using System.Linq.Expressions;

namespace Pub.Class.MongoDB.Samus
{
    /// <summary>
    /// samus驱动 db通用类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class MongoDBHelper<T> where T : class
    {
        #region property
        private string connectionString = WebConfig.GetApp("MongoServer");
        private string databaseName = WebConfig.GetApp("Database");
        private Mongo mongo;
        private MongoDatabase mongoDatabase;
        private MongoCollection<T> mongoCollection;
        #endregion

        #region 构造
        public MongoDBHelper(string name)
        {
            mongo = GetMongo();
            mongoDatabase = mongo.GetDatabase(databaseName) as MongoDatabase;
            mongoCollection = mongoDatabase.GetCollection<T>(name) as MongoCollection<T>;
            mongo.Connect();
        }
        public MongoDBHelper()
        {
            mongo = GetMongo();
            mongoDatabase = mongo.GetDatabase(databaseName) as MongoDatabase;
            mongoCollection = mongoDatabase.GetCollection<T>() as MongoCollection<T>;
            mongo.Connect();
        }
        ~MongoDBHelper()
        {
            mongo.Disconnect();
        }
        #endregion

        #region 配置Mongo,将类UserInfo映射到集合

        /// <summary>
        /// 配置Mongo,将类UserInfo映射到集合
        /// </summary>
        private Mongo GetMongo()
        {
            var config = new MongoConfigurationBuilder();
            config.Mapping(mapping =>
            {
                mapping.DefaultProfile(profile =>
                {
                    profile.SubClassesAre(t => t.IsSubclassOf(typeof(T)));
                });
                mapping.Map<T>();
            });
            config.ConnectionString(connectionString);
            return new Mongo(config.BuildConfiguration());
        }
        #endregion

        #region methods

        #region add
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="t"></param>
        public void Insert(T t)
        {
            mongoCollection.Insert(t);
        }
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="t"></param>
        public void Insert(T t, bool b)
        {
            mongoCollection.Insert(t, b);
        }
        #endregion

        #region update
        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="t"></param>
        public void Insert(T t, Expression<Func<T, bool>> func)
        {
            mongoCollection.Update(t, func, true);
        }

        public void Insert(T t, Expression<Func<T, bool>> func, UpdateFlags updateFlags)
        {
            mongoCollection.Update(t, func, updateFlags);
        }

        public void Insert(T t, Object selector, UpdateFlags updateFlags)
        {
            mongoCollection.Update(t, selector, updateFlags);
        }
        #endregion

        #region delete

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="t"></param>
        public void Delete(Expression<Func<T, bool>> func)
        {
            mongoCollection.Remove(func);
        }


        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="selector"></param>
        public void Delete(object selector)
        {
            mongoCollection.Remove(selector);
        }
        #endregion

        #region search
        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="PageIndex">总页码</param>
        /// <param name="PageSize">页容量</param>
        /// <param name="RowCounts">总记录数</param>
        /// <param name="expression">条件</param>
        /// <param name="IsAsc">是否是正序</param>
        /// <param name="OrderFiled">排序的字段</param>
        /// <returns></returns>
        public List<T> Page(int PageIndex, int PageSize, out  long RowCounts, Expression<Func<T, bool>> expression = null, bool IsAsc = true, params string[] OrderFiled)
        {
            ICursor<T> mongoCursor;

            //条件选择
            if (expression != null)
            {
                RowCounts = mongoCollection.Linq().Where(expression).Count();
                mongoCursor = mongoCollection.Find(expression);
            }
            else
            {
                RowCounts = mongoCollection.Count();
                mongoCursor = mongoCollection.FindAll();
            }

            //排序
            if (OrderFiled != null && OrderFiled.Length > 0)
            {
                for (int i = 0; i < OrderFiled.Length; i++)
                {
                    if (IsAsc)
                    {
                        mongoCursor = mongoCursor.Sort(OrderFiled);
                    }
                    else
                    {
                        mongoCursor = mongoCursor.Sort(OrderFiled[i], IndexOrder.Descending);
                    }
                }

            }

            return mongoCursor.Skip((PageIndex - 1) * PageSize).Limit(PageSize).;
        }

        /// <summary>
        /// 查询单条数据
        /// </summary>
        /// <returns></returns>
        public T SelectOne(Document spec)
        {
            return mongoCollection.FindOne(spec);

        }
        public T SelectOne(Expression<Func<T, bool>> func)
        {
            return mongoCollection.Linq().FirstOrDefault(func);
        }

        /// <summary>
        /// 查询集合数据
        /// </summary>
        /// <returns></returns>
        public List<T> SelectMore(Document spec)
        {
            return mongoCollection.Find(spec).Documents.ToList();
        }
        public List<T> SelectMore(Expression<Func<T, bool>> func)
        {
            return mongoCollection.Linq().Where(func).ToList();
        }

        /// <summary>
        /// Cursor查询所有
        /// </summary>
        /// <returns></returns>
        public Cursor SelectALl2Cursor()
        {
            return (Cursor)mongoCollection.FindAll();
        }
        /// <summary>
        /// linq查询所有
        /// </summary>
        /// <returns></returns>
        public List<T> SelectALl()
        {
            return mongoCollection.Linq().ToList();
        }

        /// <summary>
        /// 求最大最小值
        /// </summary>
        /// <param name="fieldname"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public T selectMaxMin(string fieldname, IndexOrder order)
        {
            return mongoCollection.FindAll().Sort(fieldname, order).Limit(1).Documents.FirstOrDefault();
        }

        /// <summary>
        /// MapReduce
        /// </summary>
        /// <param name="MapFunc"></param>
        /// <param name="ReduceFunc"></param>
        /// <returns></returns>
        public void CreateMapReduce(string MapFunc, string ReduceFunc, string outcollection)
        {
            mongoCollection.MapReduce()
                 .Map(MapFunc)
                   .Reduce(ReduceFunc)
                     .Out(outcollection);
        }

        #endregion

        #endregion
    }
}
